package cn.tedu.mall.order.consumer;

import cn.tedu.mall.order.service.IOrderAddService;
import cn.tedu.mall.pojo.order.dto.OrderAddCondition;
import cn.tedu.mall.pojo.order.dto.OrderAddDTO;
import cn.tedu.mall.pojo.seckill.dto.SeckillOrderAddDTO;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

import java.util.Objects;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
@RocketMQMessageListener(
        consumerGroup = "csmall-order-add-group",
        topic = "csmall-order-add-topic",
        selectorExpression = "*")
public class OrderAddConsumer implements RocketMQListener<MessageExt> {
    private static final String ORDER_ADD_LOCK = "order:add:lock:";
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private IOrderAddService orderAddService;
    @Override
    public void onMessage(MessageExt message) {
        OrderAddCondition orderAddCondition = null;
        String sn = null;
        // 从消息上下文拿到tag作为判断订单是否为秒杀订单
        String tags = message.getTags();
        String msgBody = new String(message.getBody());
        if (tags.equals("localAdd")) {
            // 接收到orderAddDTO 的 json字符串，转化成对象
            orderAddCondition = JSON.toJavaObject(JSON.parseObject(msgBody), OrderAddDTO.class);
            sn = orderAddCondition.getSn();
        } else if (tags.equals("seckillAdd")) {
            orderAddCondition = JSON.toJavaObject(JSON.parseObject(msgBody), SeckillOrderAddDTO.class);
            sn = orderAddCondition.getSn();
        }
        // 如果两个if都没满足，当前逻辑停止
        if (orderAddCondition == null || sn == null) {
            log.error("当前消息：{}，没有消费成功，tags不是选型中的内容：{}", message.getMsgId(), tags);
            return;
        }
        // 设置一个锁定的key值
        String lockKey = ORDER_ADD_LOCK + sn;
        // 生成一个随机数，抢锁 抢成功执行orderAdd方法，失败了结束
        String randCode = new Random().nextInt(9000) + 1000 + "";
        ValueOperations valueOperations = redisTemplate.opsForValue();
        try {
            // 执行抢锁 SETNX key randCode EX 10
            Boolean hasKey = valueOperations.setIfAbsent(lockKey, randCode, 10, TimeUnit.SECONDS);
            if (hasKey) {
                log.debug("拿到消费对象：{}", orderAddCondition);
                // 新增订单
                orderAddService.addOrder(orderAddCondition);
            } else {
                return;
            }
        } catch (Exception e) {
            log.error("出现不明异常：{}", e.getMessage());
            e.printStackTrace();
        } finally {
            String randCodeCache = (String) valueOperations.get(lockKey);
            if (Objects.equals(randCodeCache, randCode)) {
                redisTemplate.delete(lockKey);
            }
        }
        // 抢锁 使用sn抢锁，如果使用消息id抢锁，粒度太细，相同的sn可能有不同的消息id，不同的消息id可以抢不同的锁，导致重复消费
        // 业务逻辑 查询订单是否存在 不存在则调用orderAdd方法

    }
}
